<?php

/**
 * 作者：云喵软件开发工作室
 * 官网：https://www.meoyun.com
 */

namespace app\service;

use app\model\MessageModel;
use app\model\UsersModel;
use app\model\PostModel;
use support\exception\BusinessException;
use Respect\Validation\Validator as v;
use Respect\Validation\Exceptions\ValidationException;

/**
 * 消息服务类
 */
class MessageService
{
    /**
     * 发送消息
     *
     * @param string $userId 发送用户ID
     * @param string $toUserId 接收用户ID
     * @param string $content 消息内容
     * @param int $type 消息类型
     * @param string|null $postId 相关帖子ID（可选）
     */
    public static function sendMessage(string $userId, string $toUserId, string $content, int $type, ?string $postId = null)
    {
        try {
            // 参数验证（包含用户存在性、帖子存在性、自己给自己发消息等所有验证）
            $validateParams = self::validateSendMessageParams($userId, $toUserId, $content, $type, $postId);
            if(!$validateParams){
                return false;
            }

            // 检查是否存在重复消息（对于需要去重的消息类型）
            $existingMessage = self::checkDuplicateMessage($userId, $toUserId, $type, $postId);
            if ($existingMessage) {
                // 更新现有消息的时间戳并返回
                $existingMessage->touch();
                return $existingMessage;
            }

            // 创建新消息
            return MessageModel::create([
                'user_id' => $userId,
                'to_user_id' => $toUserId,
                'post_id' => $postId,
                'content' => $content,
                'type' => $type,
                'is_read' => 0
            ]);
        } catch (BusinessException $e) {
            // 参数验证失败，继续抛出异常
            throw $e;
        } catch (\Exception $e) {
            return false;
        }
    }


    /**
     * 验证发送消息的参数
     *
     * @param string $userId
     * @param string $toUserId
     * @param string $content
     * @param int $type
     * @param string|null $postId
     */
    private static function validateSendMessageParams(string $userId, string $toUserId, string $content, int $type, ?string $postId): bool
    {
        try {
            // 基础参数验证
            v::input([
                'user_id' => $userId,
                'to_user_id' => $toUserId,
                'content' => $content,
                'type' => $type,
                'post_id' => $postId
            ], [
                'user_id' => v::stringType()->notEmpty()->setName('发送用户ID'),
                'to_user_id' => v::stringType()->notEmpty()->setName('接收用户ID'),
                'content' => v::stringType()->notEmpty()->length(1, 255)->setName('消息内容'),
                'type' => v::intType()->in([
                    MessageModel::TYPE_LIKE,
                    MessageModel::TYPE_FAVORITE,
                    MessageModel::TYPE_COMMENT,
                    MessageModel::TYPE_FOLLOW,
                    MessageModel::TYPE_SYSTEM
                ])->setName('消息类型'),
                'post_id' => v::optional(v::stringType()->notEmpty())->setName('帖子ID')
            ]);
        } catch (ValidationException $e) {
            return false;
        }

        // 防止自己给自己发消息（除了系统消息）
        if ($userId === $toUserId && $type !== MessageModel::TYPE_SYSTEM) {
            return false;
        }

        // 根据消息类型验证 post_id 的必要性
        if (in_array($type, [MessageModel::TYPE_LIKE, MessageModel::TYPE_FAVORITE]) && !$postId) {
            return false;
        }

        if ($type === MessageModel::TYPE_FOLLOW && $postId) {
            return false;
        }

        return true;
    }


    /**
     * 检查是否存在重复消息
     * 
     * 去重规则：
     * - 点赞/收藏消息：基于用户关系和具体帖子进行去重
     * - 关注消息：仅基于用户关系进行去重
     * - 评论/系统消息：不进行去重，允许重复发送
     *
     * @param string $userId 发送用户ID
     * @param string $toUserId 接收用户ID
     * @param int $type 消息类型
     * @param string|null $postId 相关帖子ID
     * @return MessageModel|null 如果存在重复消息则返回现有消息，否则返回null
     */
    private static function checkDuplicateMessage(string $userId, string $toUserId, int $type, ?string $postId): ?MessageModel
    {
        // 根据消息类型进行不同的去重逻辑
        switch ($type) {
            case MessageModel::TYPE_LIKE:
            case MessageModel::TYPE_FAVORITE:
                // 点赞和收藏消息基于用户关系和具体帖子进行去重
                return MessageModel::where('user_id', $userId)
                    ->where('to_user_id', $toUserId)
                    ->where('type', $type)
                    ->where('post_id', $postId)
                    ->first();

            case MessageModel::TYPE_FOLLOW:
                // 关注消息仅基于用户关系进行去重，不考虑post_id的值
                return MessageModel::where('user_id', $userId)
                    ->where('to_user_id', $toUserId)
                    ->where('type', $type)
                    ->first();

            default:
                // 评论和系统消息不进行去重检查
                return null;
        }
    }
}
